startTestGroup('Extending Base Class Tests');

window.extendingClassInstances = 0;
window.ExtendingClass = jClass.extend(BaseClass)({
    constructor : function() {
        extendingClassInstances++;
    },
    public : {
        extpMethod : function() {
            return true;
        },
        extretPrivate : function() {
            return privMethod();
        },
        exttest : function() { return true; },
        extpVar : 2,
        extgetter : Get(function() {
            return 2;
        }),
        extsetter : Set(function(val) {
            _extsetter = val;
        }),
        extgetset : GetSet(function() {
            return _extgetset;
        }, function(val) {
            _extgetset = val;
        }),
        test1 : function() {},
        extstat : Static(true),
        extgetSetter : function() {
            return _setter;
        },
        tooverride : function() {
            return _super.tooverride() == false;
        },
        extoverload : Overload(function() { return 0; }, function(param) { return 1}, function(param, param1) { return 2}, function(param1, param2, param3, param4, param5) { return 5; })
    },
    private : {
        extprivMethod : function() {
            return privVar == pVar;
        },
        extprivVar : 2
    },
    static : {
        EXT_STATIC : true
    }
})
assertTrue('BaseClass constructor should not be called before instantiating object',baseClassInstances == 1);
window.x = new ExtendingClass();
assertNotNull('Testing _prototype and _prototype members', x._prototype, x._prototype.typeName, x._prototype.implementing, x._prototype.extending, x._prototype.instanceId);
assertTrue('ExtendingClass .isInstanceOf(BaseClass) should be true', x.isInstanceOf(BaseClass))
assertTrue('BaseClass constructor caled',baseClassInstances == 2);
assertTrue('ExtendingClass constructor called',extendingClassInstances == 1);

assertTrue('ExtendingClass should contain static declared members and inherited statics', ExtendingClass.STATIC, ExtendingClass.stat, ExtendingClass.EXT_STATIC, ExtendingClass.extstat);
assertNull('ExtendingClass instance should not contain static declared members and inherited statics', x.STATIC, x.stat, x.EXT_STATIC, x.extstat);

assertTrue('Accessing public member from both ExtendingClass and BaseClass', x.pMethod(), x.pVar == 2, x.extpVar == 2, x.extpMethod());
assertNull('Accessing private member should return undefined', x.extprivVar, x.extprivMethod, x.privVar, x.privMethod);
assertTrue('Accessing inherited public method that reads from BaseClass private space', x.retPrivate());
x.setter = 3;
assertNull('Testing WriteOnly properties in BaseClass', (x.getSetter() == 3 ? undefined : '!='), x.setter);
window.success = false;
try { x.getter = 2; } catch(ex) { success = (ex.message == "Property is Read-Only"); }
assertTrue('Testing ReadOnly properties in BaseClass', x.getter == 2, success);
assertTrue('Testing Overloading methods in BaseClass', x.overload() == 0, x.overload(1) == 1, x.overload(1,2) == 2, x.overload(1,2,3,4,5) == 5, x.overload(1,2,3) == 2, x.overload(1,2,3,4,5,6) == 5);
assertTrue('Overriding BaseClass method', x.tooverride(), x.testoverride());

window.tempClassInstances = 0;
startTestGroup('Multiple Inheritence Tests');
window.TempExt = jClass.extend(ExtendingClass)({
    constructor : function() {
        tempClassInstances++;
    },
    public : {
        tooverride : function() {
            return !(_super.tooverride() == true);
        }
    }
});
assertTrue('BaseClass constructor should not be called before instantiating object',baseClassInstances == 2);
assertTrue('ExtendingClass constructor should not be called before instantiating object',extendingClassInstances == 1);
window.x = new TempExt();
assertNotNull('Testing _prototype and _prototype members', x._prototype, x._prototype.typeName, x._prototype.implementing, x._prototype.extending, x._prototype.instanceId);
assertTrue('BaseClass constructor caled',baseClassInstances == 3);
assertTrue('ExtendingClass constructor called',extendingClassInstances == 2);
assertTrue('Class constructor called',extendingClassInstances == 2);
assertTrue('Testing inheritence chain (isInstanceOf) ', x.isInstanceOf(BaseClass), x.isInstanceOf(ExtendingClass))
assertTrue('Class should contain inherited statics', TempExt.STATIC, TempExt.stat, TempExt.EXT_STATIC, TempExt.extstat);
assertNull('Class instance should not contain inherited statics', x.STATIC, x.stat, x.EXT_STATIC, x.extstat);
assertTrue('Accessing public member from both ExtendingClass and BaseClass', x.pMethod(), x.pVar == 2, x.extpVar == 2, x.extpMethod());
assertNull('Accessing private member should return undefined', x.extprivVar, x.extprivMethod, x.privVar, x.privMethod);
assertTrue('Accessing inherited public method that reads from BaseClass private space', x.retPrivate());
x.setter = 3;
assertNull('Testing WriteOnly properties in BaseClass', (x.getSetter() == 3 ? undefined : '!='), x.setter);
success = false;
try { x.getter = 2; } catch(ex) { success = (ex.message == "Property is Read-Only"); }
assertTrue('Testing ReadOnly properties in BaseClass', x.getter == 2, success);
assertTrue('Testing Overloading methods in BaseClass', x.overload() == 0, x.overload(1) == 1, x.overload(1,2) == 2, x.overload(1,2,3,4,5) == 5, x.overload(1,2,3) == 2, x.overload(1,2,3,4,5,6) == 5);

delete(x);
delete(success);
delete(tempClassInstances);